from flask import session, current_app, jsonify, request,json
# 导入自定义的状态码
from info.utils.response_code import RET
# 导入模型类
from info.models import House,Area,Order
# 导入日期模块
import datetime
# 导入redis对象
from info import redis_store,constants
# 导入登陆验证装饰器
from info.utils.commons import login_required

# 导入蓝图
from . import houses_blue

@houses_blue.route("/")
def index():
    return current_app.send_static_file('html/index.html')

@houses_blue.route("/api/v1.0/areas")
def get_area_info():
    """获取城区信息"""
    # 查询数据库，获取城区信息
    try:
        areas_list = Area.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询城区信息异常")

    # 遍历列表，处理每一个对象，转换一下对象的属性名
    areas = []
    for area in areas_list:
        areas.append(area.to_dict())

    # # 将数据转换为json
    # areas_json = json.dumps(areas)
    # # 将数据在redis中保存一份缓存
    # try:
    #     redis_store.setex("area_info", constants.AREA_INFO_REDIS_EXPIRES, areas_json)
    # except Exception as e:
    #     current_app.logger.error(e)

    # 从redis中去取的json数据或者从数据库中查询并转为的json数据
    # areas_json = '[{"aid":xx, "aname":xxx}, {},{}]'

    return jsonify(errno=RET.OK,errmsg="成功",data=areas)


@houses_blue.route('/api/v1.0/houses' , methods=['GET'])
def search_houses_list():
    """
    房屋列表页
    4.1 可根据入住离开时间、区域进行筛选，并可进行排序
    4.2 房屋信息分页加载
    4.3 区域信息动态加载
    4.4 筛选条件更新后，页面立即刷新

    获取参数---检查参数---业务处理---返回结果
    1. 验证登陆
    2.# 获取参数，get请求，args属性
    :return:
    """
    # 获取参数
    start_date_str = request.args.get("sd", "")  # 想要查询的起始时间
    end_date_str = request.args.get("ed", "")  # 想要查询的终止时间
    area_id = request.args.get("aid", "")  # 区域id
    sort_key = request.args.get("sk", "new")  # 排序关键字
    page = request.args.get("p", 1)  # 页数

    # 校验参数
    # 判断日期
    try:
        start_date = None
        if start_date_str:
            start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d")

        end_date = None
        if end_date_str:
            end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d")

        if start_date and end_date:
            assert start_date <= end_date

    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg="日期参数有误")

    # 判断页数
    try:
        page = int(page)
    except Exception as e:
        page = 1

    # 先从redis缓存中获取数据
    try:
        redis_key = "houses_%s_%s_%s_%s" % (start_date_str, end_date_str, area_id, sort_key)
        resp_json = redis_store.hget(redis_key, page)
    except Exception as e:
        current_app.logger.error(e)
        resp_json = None

    if resp_json:
        # 表示从缓存中拿到了数据
        return resp_json, 200, {"Content-Type": "application/json"}

    # 查询数据
    filter_params = []

    # 处理区域信息
    if area_id:
        filter_params.append(House.area_id == area_id)

    # 处理时间
    try:
        conflict_orders_li = []
        if start_date and end_date:
            # 从订单表中查询冲突的订单，进而获取冲突的房屋id
            conflict_orders_li = Order.query.filter(Order.begin_date <= end_date,
                                                    Order.end_date >= start_date).all()
        elif start_date:
            # 从订单表中查询冲突的订单，进而获取冲突的房屋id
            conflict_orders_li = Order.query.filter(Order.end_date >= start_date).all()
        elif end_date:
            # 从订单表中查询冲突的订单，进而获取冲突的房屋id
            conflict_orders_li = Order.query.filter(Order.begin_date <= end_date).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    if conflict_orders_li:
        conflict_house_id_li = [order.house_id for order in conflict_orders_li]
        # 添加条件，查询不冲突的房屋
        filter_params.append(House.id.notin_(conflict_house_id_li))

    # 排序
    if sort_key == "booking":
        house_query = House.query.filter(*filter_params).order_by(House.order_count.desc())
    elif sort_key == "price-inc":
        house_query = House.query.filter(*filter_params).order_by(House.price.asc())
    elif sort_key == "price-des":
        house_query = House.query.filter(*filter_params).order_by(House.price.desc())
    else:
        house_query = House.query.filter(*filter_params).order_by(House.create_time.desc())

    # 分页  sqlalchemy的分页
    try:
        #                    页数     每页数量                          错误输出
        house_page = house_query.paginate(page, constants.HOUSE_LIST_PAGE_CAPACITY, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    house_li = house_page.items  # 当前页中的数据结果
    total_page = house_page.pages  # 总页数

    houses = []
    for house in house_li:
        houses.append(house.to_basic_dict())

    # 将结果转换json字符串
    resp = dict(errno=RET.OK, errmsg="查询成功",
                data={"houses": houses, "total_page": total_page, "current_page": page})
    resp_json = json.dumps(resp)

    # 将结果缓存到redis中
    if page <= total_page:
        # 用redis的哈希类型保存分页数据
        redis_key = "houses_%s_%s_%s_%s" % (start_date_str, end_date_str, area_id, sort_key)
        try:
            # 使用redis中的事务
            pipeline = redis_store.pipeline()
            # 开启事务
            pipeline.multi()
            pipeline.hset(redis_key, page, resp_json)
            pipeline.expire(redis_key, constants.HOUSE_LIST_PAGE_REDIS_EXPIRES)
            # 执行事务
            pipeline.execute()
        except Exception as e:
            current_app.logger.error(e)

    return resp_json, 200, {"Content-Type": "application/json"}


@houses_blue.route("/api/v1.0/houses/<int:house_id>",methods=["GET"])
@login_required
def get_houses_detail(house_id):
    "获取房屋详情"
    # 前端在房屋详情页面展示时，如果浏览页面的用户不是该屋的房东，则展示预定按钮，否则不展示
    # 所以需要后端返回登录用户的user_id
    # 尝试获取用户登录的信息，若登录，则返回给前端登录用户的user_id,否则返回user_id=-1
    user_id = session.get("user_id","-1")

    #校验参数
    if not house_id:
        return jsonify(errno=RET.PARAMERR,errmsg="参数确实")

    # 查询数据库
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    # 将房屋对象数据转换为字典
    try:
        house_data = house.to_full_dict()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="数据出错")
    session["house_id"] = house_id
    data = {
        "user_id":user_id,
        "house":house_data
    }

    return jsonify(errno=RET.OK,errmsg="成功",data=data)

@houses_blue.route("/api/v1.0/houses/index", methods=["GET"])
def get_house_index():
    """
    获取主页幻灯片展示的房屋基本信息
    """
    # 从缓存中尝试获取数据
    # try:
    #     my_data = redis_store.get("home_page_data")
    # except Exception as e:
    #     current_app.logger(e)
    #     my_data = None
    #
    # if my_data:
    #     return jsonify(errno=RET.NODATA, errmsg='无数据')

    try:
        # 查询数据库，返回房屋订单数目最多的5条数据
        houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES)

    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

    if not houses:
        return jsonify(errno=RET.NODATA, errmsg="查询无数据")

    houses_list = []
    for house in houses:
        # 如果房屋未设置主图片，则跳过
        if not house.index_image_url:
            continue  # 跳出此次判断继续执行下面的代码
        houses_list.append(house.to_basic_dict())

    return jsonify(errno=RET.OK,errmsg='OK',data=houses_list)

@houses_blue.route("/<path:file_name>")
def favicon(file_name):
    """
代码实现后，浏览器无法获取favicon图标的解决方法:
1.清理浏览器缓存
2.清理浏览器记录
3.彻底关闭浏览器
原因：因为浏览器加载favicon不是每次请求都加载
    :return:
    """
    if file_name != 'favicon.ico':
        file_name = 'html/' + file_name
    return current_app.send_static_file(file_name)